//封装一个Dep类,用来收集所有访问的watcher的信息,发布时通知更新
class Dep{
    constructor(){
        //在实例上放一个空数组,收集所有的依赖
        this.subs=[]
    }
    depend(watcher){
        //每次访问数据时,将watcher放入数组中
        this.subs.push(watcher)
    }
    notify(){
        // 每次数据更新时通知所有watcher更新
        this.subs.forEach(watcher=>{

        })
    }
}



//封装一个Observe类,主要用来处理发布订阅模式的核心操作(响应式操作:  收集依赖,通知更新)
class Observe {
    constructor(obj) {
        this.obj = obj
        
        //深层次数据劫持时,经过判断_data内的值是否为数组
        if (Array.isArray(obj)) {
            // 如果是数组则遍历继续判断数组内的值是否为数组
            return this.observeArray(obj)
        } else {
            this.walk(obj)
        }
    }

    observeArray(obj){
        obj.forEach(item=>{
            observer(item)
        })
    }

    walk(obj) {
        for (const key of Object.keys(obj)) {
        //将每个数据响应式的核心代码交给defineReactive处理
        defineReactive(obj,key, obj[key])
        }
    }

}

//封装defineReactive函数，主要是为了对单个数据做数据劫持（数据劫持的核心代码）
function defineReactive(obj, key, value) {
    //判断obj的每一个值进行深层次的数据劫持
    observer(value)

    Object.defineProperty(obj, key, {
        get() {
            console.log('收集所有watcher的信息');
            return value
        },
        set(newVal) {
            value = newVal
            console.log('数据更新,通知watcher重新获取值');
        },
    })
}



//定义一个observer函数 将对象内的所有属性一个个添加数据劫持
function observer(obj) {
    //深层次数据劫持时,判断_data内的属性值是否为基本类型
    if(typeof obj !== 'object' || obj===null)return

    new Observe(obj)
    
}

function Vue(options) {
    //将配置项放在Vue实例上
    this._data = options.data

    //数据代理,将this._data 的值放在this上,直接访问this.name时通过存取器属性实际上是读取,修改this._data的值
    for (let key of Object.keys(this._data)) {

        Object.defineProperty(this, key, {
            get() {
                return this._data[key]
            },
            set(value) {
                this._data[key] = value
            }
        })
    }
    observer(this._data)
}

//实例化Vue,传入配置项
const vm = new Vue({
    data: {
        name: 'laowang',
        age: 19,
        hobby: [
            {id:'001',cont:'抽烟'},
            {id:'002',cont:'喝酒'},
            {id:'003',cont:'烫头'}
        ]
    }
})




// console.log(vm);

function get() {
    console.log(vm.name);
}

function set() {
    vm.hobby[0].cont=1
}


// get()
// set()